function varargout = TLSwcsenderportDlg(action,varargin)

% TL_SWCSENDERPORT_DLG manages dialogs for TargetLink AUTOSAR ports outside of a runnable
%
% SYNTAX dlgInfo = TLSwcsenderportDlg('GetDlgInfo');
%   gets dialog info of TargetLink SWC SenderPort block
%
%   INPUT ARGUMENTS
%   -/-      
%
%   OUTPUT ARGUMENTS
%   dlgInfo     dialog information contains pageNames etc.
%
% SYNTAX [sheetDims, ctrlPos] = TLSwcsenderportDlg('CtrlPositions', pageName, commonGeom, dlgInfo, sheetDims);
%   calculates the control positions of all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   commonGeom      common geometry data
%   dlgInfo         dialog information contains pageNames etc.
%   sheetDims       dimension of sheet
%
%   OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% SYNTAX dlgdata = TLSwcsenderportDlg('Create', pageName, dlgfig, dlgdata);
%   creates all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX [dlgdata,bModified] = TLSwcsenderportDlg('Manage', pageName, dlgfig, dlgdata, pageAction);
%   manages all actions of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageAction      modified control of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%   bModified       flag = 1, if dialog data are modified, =0 otherwise
%
% SYNTAX dlgdata = TLSwcsenderportDlg('Update', dlgfig, dlgdata, pageNum);
%   updates all controls of dialog page: <pageNum>
%
%   INPUT ARGUMENTS
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageNum         number of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX TLSwcsenderportDlg('Apply', dlgfig, dlgdata);
%   writes current blockdata to block and DD
%
%   INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
%   OUTPUT ARGUMENTS
%   - / -


% Author(s): D. Andoleit, T. Pietzsch
% $RCSfile: TLSwcsenderportDlg.m $
% $ProjectName: e:/ARC/Components/HostSW/SimulinkBlocksets/TLBlocksets/AUTOSARBlockset/AUTOSARBlockset_UI/Sources/MSrc/project.pj $
% $Revision: 1.18 $
% $Date: 2011/09/02 10:02:22MESZ $
%
% Copyright ?2011 dSPACE GmbH. All rights reserved.


% branch dependend on action
switch action,
    case 'GetDlgInfo'
        hBlock = varargin{1};
        dlgInfo = tl_get_dlginfodefaults('tlsim');
        titleName = 'SWC_SenderPort';
        pathinfo = tl_pathinfo(hBlock);
        dlgInfo.title = sprintf('TargetLink %s: %s', titleName, pathinfo.shortDisplayName);
        % no associated Simulink block
        dlgInfo.bSLParamDlg = 0;
        % no link to code
        dlgInfo.bEditCode = 0;
        dlgInfo.bViewCode = 0;
        % no plot signals
        dlgInfo.bPlotSignal = 0;
        % return structure holding the names of tabs
        dlgInfo.pageNames = {
            'Output' ...
            'Documentation'};
        varargout{1} = dlgInfo;
        varargout{2} = get_tlcg_data(hBlock);
        
    case 'CtrlPositions',
        % identify input arguments
        pageName     = varargin{1};
        commonGeom   = varargin{2};
        sheetDims    = varargin{4};
        
        % branch depending on page name
        switch pageName,
            case 'Output',
                [sheetDims,ctrlPos] = FcnOutputCtrlPosition(commonGeom);
            case 'Documentation'
                bTblBlock = 0;
                bCodeComment = 0;
                [sheetDims,ctrlPos] = TLManageDocCtrls( ...
                    'ctrlpos', commonGeom, sheetDims, bCodeComment, bTblBlock);
        end
        varargout{1} = sheetDims;
        varargout{2} = ctrlPos;
        
    case 'Create'
        % identify input arguments
        pageName = varargin{1};
        dlgfig   = varargin{2};
        dlgdata  = varargin{3};
        pageNum  = strmatch(pageName,dlgdata.pageNames,'exact');
        
        switch pageName
            case 'Output'
                dlgdata = FcnCreateOutputPage(pageNum,dlgfig,dlgdata);
            case 'Documentation'
                dlgdata = ...
                    TLManageDocCtrls('create',pageNum,dlgfig,dlgdata);
        end
        dlgdata.pageData{pageNum}.ctrlPos = [];
        dlgdata.bApplyCallback = 0;
        
        varargout{1} = dlgdata;
        
    case 'Manage'
        % identify input arguments
        pageName   = varargin{1};
        dlgfig     = varargin{2};
        dlgdata    = varargin{3};
        pageAction = varargin{4};
        pageNum  = strmatch(pageName,dlgdata.pageNames,'exact');
        
        switch pageName
            case 'Output'
                [dlgdata,bModified] = ...
                    FcnManageOutputPage(dlgdata,pageAction);
            case 'Documentation'
                [dlgdata,bModified] = TLManageDocCtrls('callback', ...
                    pageNum,    ...
                    dlgfig,     ...
                    dlgdata,    ...
                    pageAction);
        end
        varargout{1} = dlgdata;
        varargout{2} = bModified;
        
    case 'Update'
        % identify input arguments
        dlgfig      = varargin{1};
        dlgdata     = varargin{2};
        pageNum   = varargin{3};
        pageName  = dlgdata.pageNames{pageNum};
        
        switch pageName
            case 'Output'
                dlgdata = FcnUpdateOutputPage(dlgfig,dlgdata,pageNum);
                
            case 'Documentation'
                TLManageDocCtrls('update', pageNum, dlgfig, dlgdata);
        end
        varargout{1} = dlgdata;
        
    case 'Apply'
        dlgdata  = varargin{2};
        bClose   = varargin{3};
        [dlgdata, bClose] = tl_apply_blockdata(dlgdata, bClose);
        varargout{1} = dlgdata;
        varargout{2} = bClose;
        
    otherwise
        error(['Invalid action ''' action'''']);
end


%--------------------------------------------------------------------------
% FcnOutputCtrlPosition calculate positions for all controls on output tab
%
% INPUT ARGUMENTS
%   commonGeom      common geometrie information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims,ctrlPos] = FcnOutputCtrlPosition(commonGeom)

% Size and style of all controlls
strings_and_styles = { ...
    'Software component: ',     'text';
    repmat('m',1,50),           'edit';
    'n',                        'pushbutton'};

% variable name, initial condition controls
[swcLabelSize, ...
    swcEditSize,   ...
    swcBrowseButtonSize] = ...
    ds_get_uicontrol_sizes(commonGeom,strings_and_styles);

% correct height, because on some platforms icon overlapped button boundary; icon height is 18 pixel.
swcBrowseButtonSize(2) = max(22, swcBrowseButtonSize(2));

% calculate max. size for one row
widths = [swcLabelSize(1), ...
    swcEditSize(1),  ...
    2*swcBrowseButtonSize(1)];

% calculate # column, column start position, column width,
% column interval (colDelta), row interval (rowDelta)
[col,colWidth,colDelta,rowDelta] = ds_get_gui_columns(widths,commonGeom);

swcEditSize(1) = swcEditSize(1) + colDelta/3;
swcGroupboxWidth = col(end) + colWidth(end) + commonGeom.frameSideEdgeBuffer;
swcGroupboxHeight = ...
    commonGeom.frameTopEdgeBuffer ...
    + 1 * rowDelta ...
    + 2 * commonGeom.editHeight  ...
    + commonGeom.frameBottomEdgeBuffer;
cx = commonGeom.figSideEdgeBuffer + commonGeom.sheetSideEdgeBuffer;
cy = commonGeom.bottomSheetOffset + commonGeom.sheetBottomEdgeBuffer;
ctrlPos.swcGroupbox = [cx,cy,swcGroupboxWidth,swcGroupboxHeight];

% software component port
cy = commonGeom.frameBottomEdgeBuffer;
cx = col(1);
ctrlPos.swcPortLabel = [cx cy swcLabelSize];

cx = col(2);
ctrlPos.swcPortEdit = [cx cy swcEditSize];

% menu button
cx = col(3) + swcBrowseButtonSize(1);
ctrlPos.swcPortMenuButton = [cx+2,cy+2,swcBrowseButtonSize(1)-4 swcBrowseButtonSize(2)-4];
% select button
dotButtonSize = [2*swcBrowseButtonSize(1) swcBrowseButtonSize(2)];
cx = col(3);
ctrlPos.swcPortSelectButton = [cx,cy, dotButtonSize];


% software component
cy = cy + commonGeom.editHeight + rowDelta;
cx = col(1);
ctrlPos.swcLabel = [cx cy swcLabelSize];

cx = col(2);
ctrlPos.swcEdit = [cx cy swcEditSize];

% menu button
cx = col(3) + swcBrowseButtonSize(1);
ctrlPos.swcMenuButton = [cx+2,cy+2,swcBrowseButtonSize(1)-4 swcBrowseButtonSize(2)-4];
% select button
dotButtonSize = [2*swcBrowseButtonSize(1) swcBrowseButtonSize(2)];
cx = col(3);
ctrlPos.swcSelectButton = [cx,cy, dotButtonSize];

% Width and height of page.
width = swcGroupboxWidth + 2 * commonGeom.sheetSideEdgeBuffer;
height = ...
    commonGeom.textHeight ...
    + swcGroupboxHeight ...
    + commonGeom.sheetBottomEdgeBuffer;
sheetDims = [width height];


%-----------------------------------------------------------------------------------------
% FcnCreateOutputPage creates the figure window
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateOutputPage(pageNum,dlgfig,dlgdata)

ctrlPos  = dlgdata.pageData{pageNum}.ctrlPos;
defColor = get(0, 'DefaultUIControlBackgroundColor');

% get arrow of context menu button
userDataMenuButton.cDataEnabled  = tl_get_icon('ArrowHeadDown_10x18', 'BackgroundColor', defColor);
userDataMenuButton.cDataDisabled = tl_get_icon('ArrowHeadDown_10x18_disabled');
userDataSelectButton.cDataEnabled  = tl_get_icon('Browse_Seperator_24x18', 'BackgroundColor', defColor);
userDataSelectButton.cDataDisabled = tl_get_icon('Browse_Seperator_24x18');

% create swcGroupbox
Children.swcGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Software component port'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.swcGroupbox);

Children.swcLabel = uicontrol( ...
    'Parent',          Children.swcGroupbox,  ...
    'Style',           'text',   ...
    'String',          'Software component:', ...
    'Position',        ctrlPos.swcLabel);

Children.swcEdit = uicontrol(    ...
    'Parent',          Children.swcGroupbox,    ...
    'Style',           'edit',    ...
    'String',          {''}, ...
    'Backgroundcolor', 'w', ...
    'enable', 'on', ...
    'Position',        ctrlPos.swcEdit);

Children.swcSelectButton = uicontrol( ...
    'Parent',            Children.swcGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataSelectButton, ...
    'CData',             userDataSelectButton.cDataEnabled, ...
    'Position',          ctrlPos.swcSelectButton);

Children.swcMenuButton = uicontrol( ...
    'Parent',            Children.swcGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataMenuButton, ...
    'CData',             userDataMenuButton.cDataEnabled, ...
    'Position',          ctrlPos.swcMenuButton);

% define context menu for software component
swcMenu = uicontextmenu('Parent', dlgfig);
set(Children.swcEdit, 'UIContextMenu', swcMenu);
set(Children.swcMenuButton, 'UIContextMenu', swcMenu);
smenu.select = uimenu(swcMenu , ...
    'Label', 'Select', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''swcSelectButton'')', ...
    dlgdata.pageNames{1}));
smenu.show = uimenu(swcMenu , ...
    'Label', 'Show in DD Manager', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''swcShowDDObject'')', ...
    dlgdata.pageNames{1}), ...
    'Separator','on');
set(swcMenu, 'UserData', smenu);

Children.swcPortLabel = uicontrol( ...
    'Parent',          Children.swcGroupbox,  ...
    'Style',           'text',   ...
    'String',          'Port:', ...
    'Position',        ctrlPos.swcPortLabel);

Children.swcPortEdit = uicontrol(    ...
    'Parent',          Children.swcGroupbox,    ...
    'Style',           'edit',    ...
    'String',          {' '}, ...
    'Value',           1, ...
    'Backgroundcolor', 'w', ...
    'enable', 'on', ...
    'Position',        ctrlPos.swcPortEdit);

Children.swcPortSelectButton = uicontrol( ...
    'Parent',            Children.swcGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataSelectButton, ...
    'CData',             userDataSelectButton.cDataEnabled, ...
    'Position',          ctrlPos.swcPortSelectButton);

Children.swcPortMenuButton = uicontrol( ...
    'Parent',            Children.swcGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataMenuButton, ...
    'CData',             userDataMenuButton.cDataEnabled, ...
    'Position',          ctrlPos.swcPortMenuButton);

% define context menu for port
portMenu = uicontextmenu('Parent', dlgfig);
set(Children.swcPortEdit, 'UIContextMenu', portMenu);
set(Children.swcPortMenuButton, 'UIContextMenu', portMenu);
pmenu.select = uimenu(portMenu, ...
    'Label', 'Select', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''swcPortSelectButton'')', ...
    dlgdata.pageNames{1}));
pmenu.show = uimenu(portMenu, ...
    'Label', 'Show in DD Manager', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''portShowDDObject'')', ...
    dlgdata.pageNames{1}), ...
    'Separator','on');
set(portMenu, 'UserData', pmenu);

dlgdata.pageData{pageNum}.children = Children;


%-----------------------------------------------------------------------------------------
% FcnManageOutputPage manage control actions of output page
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   pageAction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata,bModified] = FcnManageOutputPage(dlgdata,pageAction)

% prepare needed data
pageNum   = 1;
bModified = false;
Children  = dlgdata.pageData{pageNum}.children;
panelPos = get(Children.swcGroupbox, 'Position');

switch pageAction
    case 'swcEdit'
        swcString = get(Children.swcEdit,'String');
        bModified = true;
        dlgdata.data.softwarecomponent = strrep(swcString, '/Pool/Autosar/SoftwareComponents/', '');
        
    case 'swcMenuButton',
        FcnSetMenuPosition(Children.swcMenuButton, panelPos(1:2));
        bModified = true;
        
    case 'swcSelectButton'
        bModified = true;
        swcPath = dlgdata.data.softwarecomponent;
        swcPath = dsdd( 'SelectObject', ...
            'CurrentPath',  swcPath, ...
            'EntryPath',    '/Pool/Autosar/SoftwareComponents', ...
            'ObjectKind',   'SoftwareComponent');
        if ~isempty(swcPath)
            dlgdata.data.softwarecomponent = swcPath;
        end
        
    case 'swcShowDDObject'
        if ~isempty(dlgdata.data.softwarecomponent)
            swcPath = ['/Pool/Autosar/SoftwareComponents/' dlgdata.data.softwarecomponent];
        else
            swcPath = '/Pool/Autosar/SoftwareComponents';
        end
        dsddman('Select', swcPath);
        
    case 'swcPortEdit'
        portString = get(Children.swcPortEdit,'String');
        bModified = true;
        portString = strrep(portString, 'Ports/', '');
        dlgdata.data.port = strrep(portString, ['/Pool/Autosar/SoftwareComponents/' dlgdata.data.softwarecomponent '/'], '');
        
    case 'swcPortMenuButton',
        FcnSetMenuPosition(Children.swcPortMenuButton, panelPos(1:2));
        bModified = true;
        
    case 'swcPortSelectButton'
        bModified = true;
        portPath = dlgdata.data.port;
        swcPath = ['/Pool/Autosar/SoftwareComponents/' dlgdata.data.softwarecomponent '/Ports'];
        portPath = dsdd( 'SelectObject', ...
            'CurrentPath',  portPath, ...
            'EntryPath',    swcPath, ...
            'ObjectKind',   'SenderPort');
        if ~isempty(portPath)
            dlgdata.data.port = strrep(portPath, 'Ports/', '');
        end
        
    case 'portShowDDObject'
        if ~isempty(dlgdata.data.port)
            portPath = ['/Pool/Autosar/SoftwareComponents/' dlgdata.data.softwarecomponent '/Ports/' dlgdata.data.port];
        else
            portPath = ['/Pool/Autosar/SoftwareComponents/' dlgdata.data.softwarecomponent '/Ports'];
        end
        dsddman('Select', portPath);
        
    otherwise
        error(['Invalid control ' pageAction]);
        
end % switch(action)


%-------------------------------------------------------------------------------
% FcnSetMenuPosition calculates position of contextmenu
%
% INPUT ARGUMENTS
%   ctrlHandle  handle of control
%   panelStart  cx position of panel
%
% OUTPUT ARGUMENTS
%   - / -
%-------------------------------------------------------------------------------
function FcnSetMenuPosition(ctrlHandle, panelStart)

pos = get(ctrlHandle, 'Position') + [panelStart 0 0];
cmenu = get(ctrlHandle, 'UIContextmenu');
commonGeom = ds_get_common_geometry;
textExtent = commonGeom.textExtent;
labelStrings = get(get(cmenu, 'Children'), 'Label');
maxext = 0;
for k = 1 : numel(labelStrings)
    set(textExtent, 'String', labelStrings{k});
    ext = get(textExtent, 'Extent');
    maxext = max(maxext, ext(3));
end
position = [pos(1)-32-maxext, pos(2)];
set(cmenu, 'Position', position, 'Visible', 'on');


%--------------------------------------------------------------------------
% FcnUpdateCounterAlarmControls updates the controls of the output tab
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number (=1 for output page)
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnUpdateOutputPage(dlgfig,dlgdata,pageNum)

% early return if children are missed
Children = dlgdata.pageData{pageNum}.children;
if isempty(Children),
    return
end

data = dlgdata.data;

if dlgdata.bIsFullVs
    enableOn = 'on';
else
    enableOn = 'inactive';
end
swcEditCtrlStatus               = struct('enable', enableOn,  'string', '');
swcMenuButtonCtrlStatus         = struct('enable', flag2str(dlgdata.bIsFullVs));
swcSelectButtonCtrlStatus       = struct('enable', flag2str(dlgdata.bIsFullVs));
swcPortEditCtrlStatus           = struct('enable', enableOn,  'string', '');
swcPortMenuButtonCtrlStatus     = struct('enable', flag2str(dlgdata.bIsFullVs));
swcPortSelectButtonCtrlStatus   = struct('enable', flag2str(dlgdata.bIsFullVs));

swcCMenu = get(Children.swcMenuButton, 'UIContextMenu');
swcMenu  = get(swcCMenu, 'UserData');
portCMenu = get(Children.swcPortMenuButton, 'UIContextMenu');
portMenu  = get(portCMenu, 'UserData');
swcMenuShowStatus           = struct('enable', flag2str(dlgdata.bDSDDMan));
swcMenuSelectStatus         = struct('enable', flag2str(dlgdata.bIsFullVs));
portMenuShowStatus          = struct('enable', flag2str(dlgdata.bDSDDMan));
portMenuSelectStatus        = struct('enable', flag2str(dlgdata.bIsFullVs));

swcEditCtrlStatus.string = data.softwarecomponent;

% SWC does not exist
if ~dsdd('exist',['/Pool/Autosar/SoftwareComponents/', data.softwarecomponent])
    if ~isempty(data.softwarecomponent)
        swcEditCtrlStatus.iserror = 1;
    end
    swcPortEditCtrlStatus.enable = 'off';
    swcPortMenuButtonCtrlStatus.enable = 'off';
    swcPortSelectButtonCtrlStatus.enable = 'off';
    % disable contextmenu
    portMenuShowStatus.enable   = 'off';
    portMenuSelectStatus.enable = 'off';
else
    swcPortEditCtrlStatus.string = data.port;
    if ~isempty(data.port) && ~dsdd('exist',['/Pool/Autosar/SoftwareComponents/' data.softwarecomponent '/Ports/' data.port])
        swcPortEditCtrlStatus.iserror = 1;
    end
end

% save control status of context menu
UserData = get(swcMenu.show, 'UserData');
UserData.ctrlStatus = swcMenuShowStatus;
set(swcMenu.show, 'UserData', UserData);
UserData = get(swcMenu.select, 'UserData');
UserData.ctrlStatus = swcMenuSelectStatus;
set(swcMenu.select, 'UserData', UserData);
UserData = get(portMenu.show, 'UserData');
UserData.ctrlStatus = portMenuShowStatus;
set(portMenu.show, 'UserData', UserData);
UserData = get(portMenu.select, 'UserData');
UserData.ctrlStatus = portMenuSelectStatus;
set(portMenu.select, 'UserData', UserData);

% list of controls for which the status is set
ctrlsList = { ...
    'swcEdit' ...
    'swcMenuButton' ...
    'swcSelectButton' ...
    'swcPortEdit' ...
    'swcPortMenuButton' ...
    'swcPortSelectButton' ...
    };

for k = 1 : numel(ctrlsList)
    ctrl = ctrlsList{k};
    % set status to control
    if isfield(Children, ctrl)
        ctrl = Children.(ctrl);
        UserData = get(ctrl, 'UserData');
        UserData.ctrlStatus = eval([ctrlsList{k} 'CtrlStatus']);
        set(ctrl, 'UserData', UserData);
    end
end

% Set status of controls
TLSetCtrlsStatus(dlgfig, Children, ctrlsList)
